//
//  CalendarView.m
//  OfficeBook
//
//  Created by 孙晓奇 on 15/9/25.
//  Copyright © 2015年 sunny. All rights reserved.
//

#import "CalendarView.h"
#import "CalendarCollectionViewEditableLayout.h"
#import "CalendarEvent.h"

// Collection View Reusable Views
#import "CalendarEventCell.h"
#import "MSGridline.h"
#import "MSDashGridLine.h"
#import "MSTimeRowHeaderBackground.h"
#import "MSDayColumnHeaderBackground.h"
#import "MSDayColumnHeader.h"
#import "MSTimeRowHeader.h"
#import "MSCurrentTimeIndicator.h"
#import "MSCurrentTimeGridline.h"

#import "CoreDataHelper.h"
#import "BookingInfoModel.h"

NSString * const CalendarEventCellReuseIdentifier       = @"CalendarEventCellReuseIdentifier";
NSString * const CalendarDayColumnHeaderReuseIdentifier = @"CalendarDayColumnHeaderReuseIdentifier";
NSString * const CalendarTimeRowHeaderReuseIdentifier   = @"CalendarTimeRowHeaderReuseIdentifier";

@interface CalendarView()
<UICollectionViewDataSource, UICollectionViewDelegate, CalendarCollectionViewEditableLayoutDelegate,NSFetchedResultsControllerDelegate>

@property (nonatomic, strong) UICollectionView                     *collectionView;
@property (nonatomic, strong) CalendarCollectionViewEditableLayout *collectionViewLayout;
@property (nonatomic, strong) NSFetchedResultsController           *fetchedResultsController;

@property (nonatomic, strong) UILabel *topBarTitleLabel;
@end

@implementation CalendarView

-(instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        //top bar
        CGFloat topBarHeight = 26.f;
        UIImage *image = [PureColorImageHelper imageWithColor:@"#1182bb" withHeight:topBarHeight withWidth:CGRectGetWidth(frame)];
        UIImageView *topBarView = [[UIImageView alloc] initWithImage:image];
        [self addSubview:topBarView];
        
        UIImageView *calendarImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"calendar"]];
        [topBarView addSubview:calendarImageView];
        [calendarImageView setContentMode:UIViewContentModeScaleAspectFill];
        [calendarImageView makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(topBarView.top).offset(4);
            make.bottom.equalTo(topBarView.bottom).offset(-4);
            make.right.equalTo(topBarView.right).offset(-10);
        }];
        
        self.topBarTitleLabel = [[UILabel alloc] init];
        [topBarView addSubview:self.topBarTitleLabel];
        self.topBarTitleLabel.textAlignment = NSTextAlignmentRight;
        self.topBarTitleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
        self.topBarTitleLabel.font = [UIFont systemFontOfSize:14];
        self.topBarTitleLabel.textColor = [UIColor whiteColor];
        [self.topBarTitleLabel makeConstraints:^(MASConstraintMaker *make) {
            make.right.equalTo(calendarImageView.left).offset(-10);
            make.centerY.equalTo(topBarView.centerY);
        }];
        
        //collectionView
        CGRect collectionFrame = CGRectMake(0, topBarHeight, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame) - topBarHeight);
        self.collectionViewLayout = [[CalendarCollectionViewEditableLayout alloc] init];
        self.collectionViewLayout.collectionViewHeight = CGRectGetHeight(collectionFrame);   //告知布局器高度
        self.collectionViewLayout.cellMargin = UIEdgeInsetsMake(0, CalendarCellPadding, 0, CalendarCellPadding);
        self.collectionViewLayout.delegate = self;
        
        self.collectionView = [[UICollectionView alloc] initWithFrame:collectionFrame collectionViewLayout:self.collectionViewLayout];
        self.collectionView.delegate = self;
        self.collectionView.dataSource = self;
        self.collectionView.backgroundColor = [UIColor whiteColor];
        self.collectionView.showsHorizontalScrollIndicator = NO;
        [self addSubview:self.collectionView];
        
        //注册collection元素
        [self.collectionView registerClass:CalendarEventCell.class forCellWithReuseIdentifier:CalendarEventCellReuseIdentifier];
        [self.collectionView registerClass:MSDayColumnHeader.class forSupplementaryViewOfKind:MSCollectionElementKindDayColumnHeader withReuseIdentifier:CalendarDayColumnHeaderReuseIdentifier];
        [self.collectionView registerClass:MSTimeRowHeader.class forSupplementaryViewOfKind:MSCollectionElementKindTimeRowHeader withReuseIdentifier:CalendarTimeRowHeaderReuseIdentifier];
        
        [self.collectionViewLayout registerClass:MSCurrentTimeIndicator.class forDecorationViewOfKind:MSCollectionElementKindCurrentTimeIndicator];
        [self.collectionViewLayout registerClass:MSCurrentTimeGridline.class forDecorationViewOfKind:MSCollectionElementKindCurrentTimeVerticalGridline];
        
        [self.collectionViewLayout registerClass:MSGridline.class forDecorationViewOfKind:MSCollectionElementKindVerticalGridline];
        [self.collectionViewLayout registerClass:MSDashGridLine.class forDecorationViewOfKind: MSCollectionElementKindVerticalDashGridline];
        
        [self.collectionViewLayout registerClass:MSTimeRowHeaderBackground.class forDecorationViewOfKind:MSCollectionElementKindTimeRowHeaderBackground];
        [self.collectionViewLayout registerClass:MSDayColumnHeaderBackground.class forDecorationViewOfKind:MSCollectionElementKindDayColumnHeaderBackground];
        
        // fetchRequest
        // 修改 通过fetchedResultsController获取的数据 均会直接触发代理controllerDidChangeContent
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Event"];
        fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"start" ascending:YES]];
        // No events with undecided times or dates
        //fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(dateToBeDecided == NO) AND (timeToBeDecided == NO)"];
        // Divide into sections by the "day" key path
        self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[CoreDataHelper sharedInstance].context sectionNameKeyPath:@"day" cacheName:nil];
        self.fetchedResultsController.delegate = self;
        
        [self.fetchedResultsController performFetch:nil];
        //NSLog(@"coreData: %@", self.fetchedResultsController.fetchedObjects);
        [self loadCalendarData];
    
    }
    return self;
}

-(void)layoutSubviews {
    // 跳转至当前时间section
    [self.collectionViewLayout scrollCollectionViewToClosetSectionToCurrentTimeAnimated:NO];
}

 //网络请求
- (void)loadCalendarData
{
    HTTPManager *manager = [HTTPManager manager];
    // 一次性获取30天数据
    NSDate *startTime = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]];
    NSDate *endTime   = [startTime dateByAddingTimeInterval:60 * 60 * 24 * 30];
    
    [manager getBookingListWithStartTime:startTime endTime:endTime success:^(NSArray *responseObject) {
        NSArray *bookingList = responseObject;
        
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.dateFormat = @"h:mm aa";
        NSDateFormatter *parseFormatter = [[NSDateFormatter alloc] init];
        parseFormatter.dateFormat = @"YYYY-MM-dd HH:mm";
        [bookingList enumerateObjectsUsingBlock:^(id  _Nonnull booking, NSUInteger idx, BOOL * _Nonnull stop) {
            CalendarEvent *event = (CalendarEvent *)[[CoreDataHelper sharedInstance] newObject];
            event.subject = booking[@"subject"];
            event.start =  [parseFormatter dateFromString:booking[@"startTime"]];
            event.end = [parseFormatter dateFromString:booking[@"endTime"]];
            event.title = [NSString stringWithFormat:@"%@-%@", [dateFormatter stringFromDate:event.start], [dateFormatter stringFromDate:event.end]];
            [[CoreDataHelper sharedInstance] save];
            
            //手动刷新
            [self.collectionViewLayout invalidateLayoutCache];
            [self.collectionView reloadData];
        }];
    } failure:^(NSError *error) {
        // fail
    }];
}

#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    //手动进行数据刷新
}

#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 30;  //保留一个月
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    NSInteger dataSection = [self dataSectionConvertFromCellSection:section];
    if (dataSection == NSNotFound) {
        return 0;
    }
    //NSLog(@"items in section: %lu", (unsigned long)[(id <NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[dataSection] numberOfObjects]);
    return [(id <NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[dataSection] numberOfObjects];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CalendarEventCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CalendarEventCellReuseIdentifier forIndexPath:indexPath];
    cell.collectionViewSize = self.collectionView.frame.size;
    cell.event = [self eventAtIndexPath:indexPath];
    return cell;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *view;
    if (kind == MSCollectionElementKindDayColumnHeader) {
        MSDayColumnHeader *dayColumnHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:CalendarDayColumnHeaderReuseIdentifier forIndexPath:indexPath];
        NSDate *currentDay = [NSDate date];
        NSDate *day = [currentDay dateByAddingTimeInterval:60 * 60 * 24 * indexPath.section];
        
        NSDate *startOfDay = [[NSCalendar currentCalendar] startOfDayForDate:day];
        NSDate *startOfCurrentDay = [[NSCalendar currentCalendar] startOfDayForDate:currentDay];  //即当日凌晨
        
        dayColumnHeader.day = day;
        dayColumnHeader.currentDay = [startOfDay isEqualToDate:startOfCurrentDay];
        view = dayColumnHeader;
    }
    else if (kind == MSCollectionElementKindTimeRowHeader) {
        MSTimeRowHeader *timeRowHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:CalendarTimeRowHeaderReuseIdentifier forIndexPath:indexPath];
        
        NSDateComponents *dateComponents = [self dayForSection:indexPath.section];
        dateComponents.hour = indexPath.item;
        timeRowHeader.time = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];;
        view = timeRowHeader;
    }
    return view;
}

-(void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
    if ([((CalendarEventCell *)cell).event.flag isEqualToNumber:@(CalendarCellStatusEnumSelected)]) {
        [self.collectionViewLayout adjustFakeCell:(CalendarEventCell *)cell];
        ((CalendarEventCell *)cell).event.flag = @(CalendarEventStatusEnumUnSelected);
    }
    NSIndexPath *newCellIndexPath = [self.collectionView indexPathForItemAtPoint:self.collectionViewLayout.newCellLocation];
    if (indexPath == newCellIndexPath) {
        [self.collectionViewLayout addFakeCell:(CalendarEventCell *)cell];
    }
}

#pragma mark CalendarCollectionViewLayout delegate
// 获取段所在日期
-(NSDateComponents *)dayForSection:(NSInteger)section
{
    NSDate *day = [[NSDate date] dateByAddingTimeInterval:60 * 60 * 24 * section];
    NSDate *startOfDay = [[NSCalendar currentCalendar] startOfDayForDate:day];
    NSDateComponents *dayDateComponents = [[NSCalendar currentCalendar] components:(NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitEra) fromDate:startOfDay];
    return dayDateComponents;
}

//获取当前时间
- (NSDate *)currentTimeComponentsForCollectionView:(UICollectionView *)collectionView layout:(CalendarCollectionViewLayout *)collectionViewLayout
{
    return [NSDate date];
}

// item开始时间
-(NSDate *)collectionView:(UICollectionView *)collectionView layout:(CalendarCollectionViewLayout *)collectionViewLayout startTimeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CalendarEvent *event = [self eventAtIndexPath:indexPath];
    return event.start;
}

// item结束时间
-(NSDate *)collectionView:(UICollectionView *)collectionView layout:(CalendarCollectionViewLayout *)collectionViewLayout endTimeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CalendarEvent *event = [self eventAtIndexPath:indexPath];
    return event.end;
}

//实时更新topBarTitle
-(void)collectionView:(UICollectionView *)collectionView dateTitleAtCurrentSection:(NSInteger)section{
    NSDate *sectionDay = [[NSDate date] dateByAddingTimeInterval:section * 24 * 60 * 60];
    NSDateFormatter *dateFormatter;
    if (!dateFormatter) {
        dateFormatter = [[NSDateFormatter alloc] init];
    }
    dateFormatter.dateStyle = NSDateFormatterShortStyle;
    dateFormatter.doesRelativeDateFormatting = YES;
    NSString *relativeDate = [dateFormatter stringFromDate:sectionDay];
    dateFormatter.dateFormat = @"EEE, MMM d";
    self.topBarTitleLabel.text = [NSString stringWithFormat:@"%@ %@",relativeDate, [dateFormatter stringFromDate:sectionDay]];
}

#pragma mark - CoreData
// event indexPath
-(CalendarEvent *)eventAtIndexPath:(NSIndexPath *)indexPath {
    NSInteger dataSection = [self dataSectionConvertFromCellSection:indexPath.section];
    NSArray *items = [(id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[dataSection] objects];
    
    return [items objectAtIndex:indexPath.item];
}

-(NSInteger)cellSectionOfEvent:(CalendarEvent *)event {
    NSDate *currentDay = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]];
    NSTimeInterval timeInterval = [event.day timeIntervalSinceDate:currentDay];
    
    return (timeInterval / (60 * 60 * 24));
}

// cell section转换成CoreData Section
// @cellSection - collection View section号
// @dataSection - CoreData中数据section号
-(NSInteger)dataSectionConvertFromCellSection:(NSInteger)cellSection {
    NSDate *sectionDay = [[NSDate date] dateByAddingTimeInterval:cellSection * 24 * 60 * 60];
    NSDate *startSectionDay = [[NSCalendar currentCalendar] startOfDayForDate:sectionDay];
    int idx;
    for (idx = 0; idx < self.fetchedResultsController.sections.count; idx++) {
        NSArray *items = [(id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[idx] objects];
        CalendarEvent *firstEventInSection = items[0];  //通过每个section第一个event获取day
        if ([firstEventInSection.day isEqualToDate:startSectionDay]) {
            return idx;
        }
    }
    return NSNotFound;
}

#pragma mark CalendarCollectionViewEditableLayout delegate

//拖拽后更新cell event
-(void)collectionView:(UICollectionView *)collectionView didEndDragCell:(CalendarEventCell *)cell {
    
    //数据更新 触发controllerDidChangeContent
    cell.event.start = [self.collectionViewLayout timeAtPoint:(CGPoint){CGRectGetMinX(cell.frame) + CGRectGetWidth(cell.leftDrag.frame)/2, 0}];
    cell.event.end   = [self.collectionViewLayout timeAtPoint:(CGPoint){CGRectGetMaxX(cell.frame) - CGRectGetWidth(cell.rightDrag.frame)/2, 0}];
    
    cell.event.start = [CalendarCollectionViewLayout formatEventTime:cell.event.start];
    cell.event.end   = [CalendarCollectionViewLayout formatEventTime:cell.event.end];
    
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"h:mm aa";
    cell.event.title = [NSString stringWithFormat:@"%@-%@", [dateFormatter stringFromDate:cell.event.start], [dateFormatter stringFromDate:cell.event.end]];
    
    cell.event.flag = @(CalendarCellStatusEnumSelected);
    [[CoreDataHelper sharedInstance] save];
    
    //手动刷新
    [self.collectionViewLayout invalidateLayoutCache];
    [self.collectionView reloadData];
    
    self.selectedEventInfo.start = cell.event.start;
    self.selectedEventInfo.end = cell.event.end;
}

-(void)collectionView:(UICollectionView *)collectionView didEndLongPressCell:(CalendarEventCell *)cell {
    self.selectedEventInfo.start = cell.event.start;
    self.selectedEventInfo.end = cell.event.end;
}

//长按创建日历事件
-(void)collectionView:(UICollectionView *)collectionView createItemAtLocation:(CGPoint)location {
    CalendarEvent *event = (CalendarEvent *)[[CoreDataHelper sharedInstance] newObject];
    //数据更新 触发controllerDidChangeContent
    NSDate *center = [self.collectionViewLayout timeAtPoint:location];
    event.start = [CalendarCollectionViewLayout formatEventTime:[center dateByAddingTimeInterval:-DefaultCellDuration/2]];
    event.end   = [CalendarCollectionViewLayout formatEventTime:[event.start dateByAddingTimeInterval: DefaultCellDuration]];
    
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"h:mm aa";
    event.title = [NSString stringWithFormat:@"%@-%@", [dateFormatter stringFromDate:event.start], [dateFormatter stringFromDate:event.end]];
    [[CoreDataHelper sharedInstance] save];
    
    //手动刷新
    [self.collectionViewLayout invalidateLayoutCache];
    [self.collectionView reloadData];

}

//轻点 显示event详情并且可编辑
-(void)collectionView:(UICollectionView *)collectionView shouldShowDetailForItemAtIndexPath:(NSIndexPath *)indexPath {
    CalendarEvent *event = [self eventAtIndexPath:indexPath];
    self.selectedEventInfo.start = event.start;
    self.selectedEventInfo.end = event.end;
    self.selectedEventInfo.subject = event.subject;
    
    [self.delegate view:self didSelectedCalendarEvent:event withBookingInfo:self.selectedEventInfo];
}

// edit booking event
-(void)calendarEvent:(CalendarEvent *)event updatedBookingInfo:(BookingInfoModel *)updated {
    event.start = updated.start;
    event.end = updated.end;
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"h:mm aa";
    event.title = [NSString stringWithFormat:@"%@-%@", [dateFormatter stringFromDate:event.start], [dateFormatter stringFromDate:event.end]];
    event.subject = updated.subject;
    event.location = updated.location;
    //编辑为Selected 将会在collectionView:willDisplayCell:forItemAtIndexPath中同步更新fakecell位置
    event.flag = @(CalendarCellStatusEnumSelected);
    [[CoreDataHelper sharedInstance] save];
    
    //手动刷新
    [self.collectionViewLayout invalidateLayoutCache];
    [self.collectionView reloadData];
}

// delete booking event
-(void)deleteCalendarEvent:(CalendarEvent *)event {
    [[CoreDataHelper sharedInstance] deleteObject:event];
    //同时需要删除fake Cell
    [self.collectionViewLayout removeFakeCell];
    //手动刷新
    [self.collectionViewLayout invalidateLayoutCache];
    [self.collectionView reloadData];
}

@end
